/**
 @ Name：layui.cron Cron表达式解析器
 @ Author：贝哥哥
 @ License：MIT
 */

layui.define(['lay', 'element', 'form'], function (exports) { //假如该组件依赖 layui.form
    var $ = layui.$
        , layer = layui.layer
        , lay = layui.lay
        , element = layui.element
        , form = layui.form


        //字符常量
        , MOD_NAME = 'cron', ELEM = '.layui-cron', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide'

        , ELEM_STATIC = 'layui-cron-static', ELEM_FOOTER = 'layui-cron-footer', ELEM_CONFIRM = '.cron-btns-confirm',
        ELEM_HINT = 'layui-cron-hint'

        , ELEM_RUN_HINT = 'layui-cron-run-hint'

        //外部接口
        , cron = {
            v: '2.0.0' // cron 组件当前版本
            , index: layui.cron ? (layui.cron.index + 10000) : 0 // corn 实例标识

            //设置全局项
            , set: function (options) {
                var that = this;
                that.config = $.extend({}, that.config, options);
                return that;
            }

            //事件监听
            , on: function (events, callback) {
                return layui.onevent.call(this, MOD_NAME, events, callback);
            }

            //主体CSS等待事件
            , ready: function (fn) {
                var cssPath = layui.cache.base + "/cron.css?v=" + cron.v;
                layui.link(cssPath, fn, "cron"); //此处的“cron”要对应 cron.css 中的样式： html #layuicss-cron{}
                return this;
            }
        }

        //操作当前实例
        , thisIns = function () {
            var that = this
                , options = that.config
                , id = options.id || options.index;

            return {
                //提示框
                hint: function (content) {
                    that.hint.call(that, content);
                }
                , config: options
            }
        }

        //构造器，创建实例
        , Class = function (options) {
            var that = this;
            that.index = ++cron.index;
            that.config = $.extend({}, that.config, cron.config, options);
            cron.ready(function () {
                that.init();
            });
        };

    //默认配置
    Class.prototype.config = {
        value: null // 当前表达式值，每秒执行一次
        ,
        isInitValue: true //用于控制是否自动向元素填充初始值（需配合 value 参数使用）
        ,
        lang: "cn" //语言，只支持cn/en，即中文和英文
        ,
        tabs: [{key: 'seconds', range: '0-59'}, {key: 'minutes', range: '0-59'}, {
            key: 'hours',
            range: '0-23'
        }, {key: 'days', range: '1-31'}, {key: 'months', range: '1-12'}, {key: 'weeks', range: '1-7'}, {key: 'years'}]
        ,
        defaultCron: {seconds: "*", minutes: "*", hours: "*", days: "*", months: "*", weeks: "?", years: ""}
        ,
        trigger: "click" //呼出控件的事件
        ,
        btns: ['run', 'confirm'] //右下角显示的按钮，会按照数组顺序排列
        ,
        position: null //控件定位方式定位, 默认absolute，支持：fixed/absolute/static
        ,
        zIndex: null //控件层叠顺序
        ,
        show: false //是否直接显示，如果设置 true，则默认直接显示控件
        ,
        showBottom: true //是否显示底部栏
        ,
        done: null //控件选择完毕后的回调，点击运行/确定也均会触发
        ,
        run: null // 最近运行时间接口
    };

    //多语言
    Class.prototype.lang = function () {
        var that = this
            , options = that.config
            , text = {
            cn: {
                tabs: [{title: "秒"}
                    , {title: "分"}
                    , {title: "时"}
                    , {title: "日"}
                    , {title: "月"}
                    , {title: "周", rateBegin: "第", rateMid: "周的星期", rateEnd: ""}
                    , {title: "年"}]
                , every: "每"
                , unspecified: "不指定"
                , period: "周期"
                , periodFrom: "从"
                , rate: "按照"
                , rateBegin: "从"
                , rateMid: "开始，每"
                , rateEnd: "执行一次"
                , weekday: "工作日"
                , weekdayPrefix: "每月"
                , weekdaySuffix: "号最近的那个工作日"
                , lastday: "本月最后一日"
                , lastweek: "本月最后一个星期"
                , custom: "指定"
                , tools: {
                    confirm: '确定'
                    , run: '运行'
                }
                , formatError: ['Cron格式不合法', '<br>已为你重置']
            }
            , en: {
                tabs: [{title: "Seconds"}
                    , {title: "Minutes"}
                    , {title: "Hours"}
                    , {title: "Days"}
                    , {title: "Months"}
                    , {title: "Weeks"}
                    , {title: "Years"}]
                , every: "Every "
                , unspecified: "Unspecified"
                , period: "Period"
                , periodFrom: "From"
                , rate: "According to"
                , rateBegin: "begin at"
                , rateMid: ", every"
                , rateEnd: " execute once"
                , weekday: "Weekday"
                , weekdayPrefix: "Every month at "
                , weekdaySuffix: "号最近的那个工作日"
                , lastday: "Last day of the month"
                , lastweek: "本月最后一个星期"
                , custom: "Custom"
                , tools: {
                    confirm: 'Confirm'
                    , run: 'Run'
                }
                , formatError: ['The cron format error', '<br>It has been reset']
            }
        };
        return text[options.lang] || text['cn'];
    };

    //初始准备
    Class.prototype.init = function () {
        var that = this
            , options = that.config
            , isStatic = options.position === 'static';

        options.elem = lay(options.elem);

        options.eventElem = lay(options.eventElem);

        if (!options.elem[0]) return;

        //如果不是input|textarea元素，则默认采用click事件
        if (!that.isInput(options.elem[0])) {
            if (options.trigger === 'focus') {
                options.trigger = 'click';
            }
        }

        // 设置渲染所绑定元素的唯一KEY
        if (!options.elem.attr('lay-key')) {
            options.elem.attr('lay-key', that.index);
            options.eventElem.attr('lay-key', that.index);
        }

        // 当前实例主面板ID
        that.elemID = 'layui-icon' + options.elem.attr('lay-key');

        //默认赋值
        if (options.value && options.isInitValue) {
            that.setValue(options.value);
        }
        if (!options.value) {
            options.value = options.elem[0].value || '';
        }
        var cronArr = options.value.split(' ');
        if (cronArr.length >= 6) {
            options.cron = {
                seconds: cronArr[0],
                minutes: cronArr[1],
                hours: cronArr[2],
                days: cronArr[3],
                months: cronArr[4],
                weeks: cronArr[5],
                years: "",
            };
        } else {
            options.cron = lay.extend({}, options.defaultCron);
        }


        if (options.show || isStatic) that.render();
        isStatic || that.events();


    };


    // 控件主体渲染
    Class.prototype.render = function () {
        var that = this
            , options = that.config
            , lang = that.lang()
            , isStatic = options.position === 'static'
            , tabFilter = 'cron-tab' + options.elem.attr('lay-key')
            //主面板
            , elem = that.elem = lay.elem('div', {
                id: that.elemID
                , 'class': [
                    'layui-cron'
                    , isStatic ? (' ' + ELEM_STATIC) : ''
                ].join('')
            })

            // tab 内容区域
            , elemTab = that.elemTab = lay.elem('div', {
                'class': 'layui-tab layui-tab-card',
                'lay-filter': tabFilter
            })
            , tabHead = lay.elem('ul', {
                'class': 'layui-tab-title'
            })
            , tabContent = lay.elem('div', {
                'class': 'layui-tab-content'
            })

            //底部区域
            , divFooter = that.footer = lay.elem('div', {
                'class': ELEM_FOOTER
            });

        if (options.zIndex) elem.style.zIndex = options.zIndex;

        // 生成tab 内容区域
        elemTab.appendChild(tabHead);
        elemTab.appendChild(tabContent);
        lay.each(lang.tabs, function (i, item) {
            // 表头
            var li = lay.elem('li', {
                'class': i === 0 ? THIS : "",
                'lay-id': i
            });
            li.innerHTML = item.title;
            tabHead.appendChild(li);

            // 表体
            tabContent.appendChild(that.getTabContentChildElem(i));
        });

        // 主区域
        elemMain = that.elemMain = lay.elem('div', {
            'class': 'layui-cron-main'
        });
        elemMain.appendChild(elemTab);

        //生成底部栏
        lay(divFooter).html(function () {
            var html = [], btns = [];
            lay.each(options.btns, function (i, item) {
                var title = lang.tools[item] || 'btn';
                btns.push('<span lay-type="' + item + '" class="cron-btns-' + item + '">' + title + '</span>');
            });
            html.push('<div class="cron-footer-btns">' + btns.join('') + '</div>');
            return html.join('');
        }());

        //插入到主区域
        elem.appendChild(elemMain);

        options.showBottom && elem.appendChild(divFooter);


        //移除上一个控件
        that.remove(Class.thisElemCron);

        //如果是静态定位，则插入到指定的容器中，否则，插入到body
        isStatic ? options.elem.append(elem) : (
            document.body.appendChild(elem)
                , that.position()
        );


        that.checkCron();

        that.elemEvent(); // 主面板事件

        Class.thisElemCron = that.elemID;

        form.render();

    }

    // 渲染 tab 子控件
    Class.prototype.getTabContentChildElem = function (index) {
        var that = this,
            options = that.config,
            tabItem = options.tabs[index],
            tabItemKey = tabItem.key,
            lang = that.lang(),
            tabItemLang = lang.tabs[index],
            cron = options.cron,
            formFilter = 'cronForm' + tabItemKey + options.elem.attr('lay-key')
            , data = function () {
                if (cron[tabItemKey].indexOf('-') != -1) {
                    // 周期数据
                    var arr = cron[tabItemKey].split('-');
                    return {
                        type: 'range',
                        start: arr[0],
                        end: arr[1]
                    };
                }
                if (cron[tabItemKey].indexOf('/') != -1) {
                    // 频率数据
                    var arr = cron[tabItemKey].split('/');
                    return {
                        type: 'rate',
                        begin: arr[0],
                        rate: arr[1]
                    };
                }
                if (cron[tabItemKey].indexOf(',') != -1 || /^\+?[0-9][0-9]*$/.test(cron[tabItemKey])) {
                    // 按照指定执行
                    var arr = cron[tabItemKey].split(',').map(Number);
                    return {
                        type: 'custom',
                        values: arr
                    };
                }
                if (cron[tabItemKey].indexOf('W') != -1) {
                    // 最近的工作日
                    var value = cron[tabItemKey].replace('W', '');
                    return {
                        type: 'weekday',
                        value: value
                    };
                }
                if (index === 3 && cron[tabItemKey] === 'L') {
                    // 本月最后一日
                    return {
                        type: 'lastday',
                        value: 'L'
                    };
                }
                if (index === 5 && cron[tabItemKey].indexOf('L') != -1) {
                    // 本月最后一个周 value
                    var value = cron[tabItemKey].replace('L', '');
                    return {
                        type: 'lastweek',
                        value: value
                    };
                }
                if (cron[tabItemKey] === '*') {
                    // 每次
                    return {
                        type: 'every',
                        value: '*'
                    };
                }
                if (cron[tabItemKey] === '?' || cron[tabItemKey] === undefined || cron[tabItemKey] === '') {
                    // 不指定
                    return {
                        type: 'unspecified',
                        value: cron[tabItemKey]
                    };
                }
            }()
            , rangeData = function () {
                if (tabItem.range) {
                    var arr = tabItem.range.split('-');
                    return {
                        min: parseInt(arr[0]),
                        max: parseInt(arr[1])
                    };
                }
            }();
        var elem = lay.elem('div', {
            'class': 'layui-tab-item layui-form ' + (index === 0 ? SHOW : "")
            , 'lay-filter': formFilter
        });

        // 每次
        elem.appendChild(function () {
            var everyRadio = lay.elem('input', {
                'name': tabItemKey + '[type]'
                , 'type': 'radio'
                , 'value': 'every'
                , 'title': lang.every + tabItemLang.title
            });
            if (data.type === 'every') {
                lay(everyRadio).attr('checked', true);
            }
            var everyDiv = lay.elem('div', {
                'class': 'cron-row'
            });
            everyDiv.appendChild(everyRadio);
            return everyDiv;
        }());

        // 不指定，从日开始
        if (index >= 3) {
            elem.appendChild(function () {
                var unspecifiedRadio = lay.elem('input', {
                    'name': tabItemKey + '[type]'
                    , 'type': 'radio'
                    , 'value': 'unspecified'
                    , 'title': lang.unspecified
                });
                if (data.type === 'unspecified') {
                    lay(unspecifiedRadio).attr('checked', true);
                }
                var unspecifiedDiv = lay.elem('div', {
                    'class': 'cron-row'
                });
                unspecifiedDiv.appendChild(unspecifiedRadio);
                return unspecifiedDiv;
            }());
        }

        // 周期
        var rangeChild = [function () {
            var rangeRadio = lay.elem('input', {
                'name': tabItemKey + '[type]'
                , 'type': 'radio'
                , 'value': 'range'
                , 'title': lang.period
            });
            if (data.type === 'range') {
                lay(rangeRadio).attr('checked', true);
            }
            return rangeRadio;
        }(), function () {
            var elem = lay.elem('div', {
                'class': 'cron-input-mid'
            });
            elem.innerHTML = lang.periodFrom;
            return elem;
        }(), function () {
            var elem = lay.elem('input', {
                'class': 'cron-input',
                'type': 'number',
                'name': 'rangeStart',
                'value': data.start || ''
            });
            return elem;
        }(), function () {
            var elem = lay.elem('div', {
                'class': 'cron-input-mid'
            });
            elem.innerHTML = '-';
            return elem;
        }(), function () {
            var elem = lay.elem('input', {
                'class': 'cron-input',
                'type': 'number',
                'name': 'rangeEnd',
                'value': data.end || ''
            });
            return elem;
        }(), function () {
            var elem = lay.elem('div', {
                'class': 'cron-input-mid'
            });
            elem.innerHTML = tabItemLang.title;
            return elem;
        }()]

            , rangeDiv = lay.elem('div', {
            'class': 'cron-row'
        });
        lay.each(rangeChild, function (i, item) {
            rangeDiv.appendChild(item);
        });
        if (tabItem.range) {
            var rangeTip = lay.elem('div', {
                'class': 'cron-tips'
            });
            rangeTip.innerHTML = ['(', tabItem.range, ')'].join('');
            rangeDiv.appendChild(rangeTip);
        }
        elem.appendChild(rangeDiv);

        // 频率,年没有
        if (index < 6) {
            var rateChild = [function () {
                var rateRadio = lay.elem('input', {
                    'name': tabItemKey + '[type]'
                    , 'type': 'radio'
                    , 'value': 'rate'
                    , 'title': lang.rate
                });
                if (data.type === 'rate') {
                    lay(rateRadio).attr('checked', true);
                }
                return rateRadio;
            }(), function () {
                var elem = lay.elem('div', {
                    'class': 'cron-input-mid'
                });
                elem.innerHTML = tabItemLang.rateBegin || lang.rateBegin;
                return elem;
            }(), function () {
                var elem = lay.elem('input', {
                    'class': 'cron-input',
                    'type': 'number',
                    'name': 'begin',
                    'value': data.begin || ''
                });
                return elem;
            }(), function () {
                var elem = lay.elem('div', {
                    'class': 'cron-input-mid'
                });
                elem.innerHTML = tabItemLang.rateMid || (tabItemLang.title + lang.rateMid);
                return elem;
            }(), function () {
                var elem = lay.elem('input', {
                    'class': 'cron-input',
                    'type': 'number',
                    'name': 'rate',
                    'value': data.rate || ''
                });
                return elem;
            }(), function () {
                var elem = lay.elem('div', {
                    'class': 'cron-input-mid'
                });
                elem.innerHTML = undefined != tabItemLang.rateEnd ? tabItemLang.rateEnd : (tabItemLang.title + lang.rateEnd);
                if (undefined != tabItemLang.rateEnd && tabItemLang.rateEnd === '') {
                    lay(elem).addClass(HIDE);
                }
                return elem;
            }()]

                , rateDiv = lay.elem('div', {
                'class': 'cron-row'
            });
            lay.each(rateChild, function (i, item) {
                rateDiv.appendChild(item);
            });
            if (tabItem.range) {
                var rateTip = lay.elem('div', {
                    'class': 'cron-tips'
                });
                if (index === 5) {
                    // 周
                    rateTip.innerHTML = '(1-4/1-7)';
                } else {
                    rateTip.innerHTML = ['(', rangeData.min, '/', (rangeData.max + (index <= 2 ? 1 : 0)), ')'].join('');
                }
                rateDiv.appendChild(rateTip);
            }
            elem.appendChild(rateDiv);
        }

        // 特殊：日（最近的工作日、最后一日），周（最后一周）
        if (index === 3) {
            // 日
            // 最近的工作日
            var weekChild = [function () {
                var weekRadio = lay.elem('input', {
                    'name': tabItemKey + '[type]'
                    , 'type': 'radio'
                    , 'value': 'weekday'
                    , 'title': lang.weekday
                });
                if (data.type === 'weekday') {
                    lay(weekRadio).attr('checked', true);
                }
                return weekRadio;
            }(), function () {
                var elem = lay.elem('div', {
                    'class': 'cron-input-mid'
                });
                elem.innerHTML = lang.weekdayPrefix;
                return elem;
            }(), function () {
                var elem = lay.elem('input', {
                    'class': 'cron-input',
                    'type': 'number',
                    'name': 'weekday',
                    'value': data.value || ''
                });
                return elem;
            }(), function () {
                var elem = lay.elem('div', {
                    'class': 'cron-input-mid'
                });
                elem.innerHTML = lang.weekdaySuffix;
                return elem;
            }(), function () {
                var elem = lay.elem('div', {
                    'class': 'cron-tips'
                });
                elem.innerHTML = ['(', tabItem.range, ')'].join('');
                return elem;
            }()]

                , weekDiv = lay.elem('div', {
                'class': 'cron-row'
            });
            lay.each(weekChild, function (i, item) {
                weekDiv.appendChild(item);
            });
            elem.appendChild(weekDiv);

            // 本月最后一日
            elem.appendChild(function () {
                var lastRadio = lay.elem('input', {
                    'name': tabItemKey + '[type]'
                    , 'type': 'radio'
                    , 'value': 'lastday'
                    , 'title': lang.lastday
                });
                if (data.type === 'lastday') {
                    lay(lastRadio).attr('checked', true);
                }
                var lastDiv = lay.elem('div', {
                    'class': 'cron-row'
                });
                lastDiv.appendChild(lastRadio);
                return lastDiv;
            }());

        }

        if (index === 5) {
            // 本月最后一个周几
            var lastWeekChild = [function () {
                var lastWeekRadio = lay.elem('input', {
                    'name': tabItemKey + '[type]'
                    , 'type': 'radio'
                    , 'value': 'lastweek'
                    , 'title': lang.lastweek
                });
                if (data.type === 'lastweek') {
                    lay(lastWeekRadio).attr('checked', true);
                }
                return lastWeekRadio;
            }(), function () {
                var elem = lay.elem('input', {
                    'class': 'cron-input',
                    'type': 'number',
                    'name': 'lastweek',
                    'value': data.value || ''
                });
                return elem;
            }(), function () {
                var elem = lay.elem('div', {
                    'class': 'cron-tips'
                });
                elem.innerHTML = ['(', tabItem.range, ')'].join('');
                return elem;
            }()]

                , lastWeekDiv = lay.elem('div', {
                'class': 'cron-row'
            });
            lay.each(lastWeekChild, function (i, item) {
                lastWeekDiv.appendChild(item);
            });
            elem.appendChild(lastWeekDiv);

        }

        // 指定
        if (index <= 5) {
            elem.appendChild(function () {
                var customRadio = lay.elem('input', {
                    'name': tabItemKey + '[type]'
                    , 'type': 'radio'
                    , 'value': 'custom'
                    , 'title': lang.custom
                });
                if (data.type === 'custom') {
                    lay(customRadio).attr('checked', true);
                }
                var customDiv = lay.elem('div', {
                    'class': 'cron-row'
                });
                customDiv.appendChild(customRadio);
                return customDiv;
            }());

            // 指定数值，时分秒显示两位数，自动补零
            elem.appendChild(function () {
                var customGrid = lay.elem('div', {
                    'class': 'cron-grid'
                });
                var i = rangeData.min;
                while (i <= rangeData.max) {
                    // 时分秒显示两位数，自动补零
                    var gridItemValue = index <= 2 ? lay.digit(i, 2) : i;
                    var gridItem = lay.elem('input', {
                        'type': 'checkbox',
                        'title': gridItemValue,
                        'lay-skin': 'primary',
                        'name': tabItemKey + '[custom]',
                        'value': i
                    });
                    if (data.values && data.values.includes(i)) {
                        lay(gridItem).attr('checked', true);
                    }
                    customGrid.appendChild(gridItem);
                    i++;
                }
                return customGrid;
            }());
        }


        return elem;
    }

    //是否输入框
    Class.prototype.isInput = function (elem) {
        return /input|textarea/.test(elem.tagName.toLocaleLowerCase());
    };

    // 绑定的元素事件处理
    Class.prototype.events = function () {
        var that = this
            , options = that.config

            //绑定呼出控件事件
            , showEvent = function (elem, bind) {
                elem.on(options.trigger, function () {
                    bind && (that.bindElem = this);
                    that.render();
                });
            };

        if (!options.elem[0] || options.elem[0].eventHandler) return;

        showEvent(options.elem, 'bind');
        showEvent(options.eventElem);

        //绑定关闭控件事件
        lay(document).on('click', function (e) {
            if (e.target === options.elem[0]
                || e.target === options.eventElem[0]
                || e.target === lay(options.closeStop)[0]) {
                return;
            }
            that.remove();
        }).on('keydown', function (e) {
            if (e.keyCode === 13) {
                if (lay('#' + that.elemID)[0] && that.elemID === Class.thisElemDate) {
                    e.preventDefault();
                    lay(that.footer).find(ELEM_CONFIRM)[0].click();
                }
            }
        });

        //自适应定位
        lay(window).on('resize', function () {
            if (!that.elem || !lay(ELEM)[0]) {
                return false;
            }
            that.position();
        });

        options.elem[0].eventHandler = true;
    };

    // 主面板事件
    Class.prototype.elemEvent = function () {
        var that = this
            , options = that.config
            , tabFilter = 'cron-tab' + options.elem.attr('lay-key');

        // 阻止主面板点击冒泡，避免因触发文档事件而关闭主面
        lay(that.elem).on('click', function (e) {
            lay.stope(e);
        });

        // tab选项卡切换
        var lis = lay(that.elemTab).find('li');
        lis.on('click', function () {
            var layid = lay(this).attr('lay-id');
            if (undefined === layid) {
                return;
            }
            element.tabChange(tabFilter, layid);
        });

        // cron选项点击
        form.on('radio', function (data) {
            var $parent = data.othis.parent();
            var formFilter = $parent.parent().attr('lay-filter');
            var formData = form.val(formFilter);
            var radioType = data.value;
            if ('range' === radioType) {
                // 范围
                form.val(formFilter, {
                    rangeStart: formData.rangeStart || 0,
                    rangeEnd: formData.rangeEnd || 2
                });
            }
            if ('rate' === radioType) {
                // 频率
                form.val(formFilter, {
                    begin: formData.begin || 0,
                    rate: formData.rate || 2
                });
            }
            if ('custom' === radioType) {
                // custom
                var $grid = $parent.next();
                if ($grid.find(':checkbox:checked').length <= 0) {
                    $grid.children(':checkbox:first').next().click()
                }
            }
            if ('weekday' === radioType) {
                // weekday
                form.val(formFilter, {
                    weekday: formData.weekday || 1
                });
            }
            if ('lastweek' === radioType) {
                // lastweek
                form.val(formFilter, {
                    lastweek: formData.lastweek || 1
                });
            }

        });

        //点击底部按钮
        lay(that.footer).find('span').on('click', function () {
            var type = lay(this).attr('lay-type');
            that.tool(this, type);
        });
    };

    //底部按钮点击事件
    Class.prototype.tool = function (btn, type) {
        var that = this
            , options = that.config
            , lang = that.lang()
            , isStatic = options.position === 'static'
            , active = {
            //运行
            run: function () {
                var value = that.parse();
                var loading = layer.load();
                $.get(options.run, {cron: value}, function (res) {
                    layer.close(loading);
                    if (res.code !== 0) {
                        return that.hint(res.msg);
                    }
                    that.runHint(res.data);
                }, 'json').fail(function () {
                    layer.close(loading);
                    that.hint('服务器异常！');
                });
            }

            //确定
            , confirm: function () {
                var value = that.parse();
                that.done([value]);
                that.setValue(value).remove()
            }
        };
        active[type] && active[type]();
    };

    //执行 done/change 回调
    Class.prototype.done = function (param, type) {
        var that = this
            , options = that.config;

        param = param || [that.parse()];
        typeof options[type || 'done'] === 'function' && options[type || 'done'].apply(options, param);

        return that;
    };

    // 解析cron表达式
    Class.prototype.parse = function () {
        var that = this
            , options = that.config
            , valueArr = [];

        lay.each(options.tabs, function (index, item) {
            var key = item.key;
            var formFilter = 'cronForm' + key + options.elem.attr('lay-key');
            var formData = form.val(formFilter);
            var radioType = (key + '[type]');
            var current = "";
            if (formData[radioType] === 'every') {
                // 每次
                current = "*";
            }
            if (formData[radioType] === 'range') {
                // 范围
                current = formData.rangeStart + "-" + formData.rangeEnd;
            }
            if (formData[radioType] === 'rate') {
                // 频率
                current = formData.begin + "/" + formData.rate;
            }
            if (formData[radioType] === 'custom') {
                // 指定
                var checkboxName = (item.key + '[custom]');
                var customArr = [];
                $('input[name="' + checkboxName + '"]:checked').each(function () {
                    customArr.push($(this).val());
                });
                current = customArr.join(',');
            }
            if (formData[radioType] === 'weekday') {
                // 每月 formData.weekday 号最近的那个工作日
                current = formData.weekday + "W";
            }
            if (formData[radioType] === 'lastday') {
                // 本月最后一日
                current = "L";
            }
            if (formData[radioType] === 'lastweek') {
                // 本月最后星期
                current = formData.lastweek + "L";
            }

            if (formData[radioType] === 'unspecified' && index != 6) {
                // 不指定
                current = "?";
            }
            if (current !== "") {
                valueArr.push(current);
                options.cron[key] = current;
            }
        });
        return valueArr.join(' ');
    };

    //控件移除
    Class.prototype.remove = function (prev) {
        var that = this
            , options = that.config
            , elem = lay('#' + (prev || that.elemID));
        if (!elem[0]) return that;

        if (!elem.hasClass(ELEM_STATIC)) {
            that.checkCron(function () {
                elem.remove();
            });
        }
        return that;
    };

    //定位算法
    Class.prototype.position = function () {
        var that = this
            , options = that.config;
        lay.position(that.bindElem || options.elem[0], that.elem, {
            position: options.position
        });
        return that;
    };

    //提示
    Class.prototype.hint = function (content) {
        var that = this
            , options = that.config
            , div = lay.elem('div', {
            'class': ELEM_HINT
        });

        if (!that.elem) return;

        div.innerHTML = content || '';
        lay(that.elem).find('.' + ELEM_HINT).remove();
        that.elem.appendChild(div);

        clearTimeout(that.hinTimer);
        that.hinTimer = setTimeout(function () {
            lay(that.elem).find('.' + ELEM_HINT).remove();
        }, 3000);
    };

    //运行提示
    Class.prototype.runHint = function (runList) {
        var that = this
            , options = that.config
            , div = lay.elem('div', {
            'class': ELEM_RUN_HINT
        });
        // debugger;
        if (!that.elem || !runList || !runList.length) return;


        lay(div).html(function () {
            var html = [];
            lay.each(runList, function (i, item) {
                html.push('<div class="cron-run-list">' + item + '</div>');
            });
            return html.join('');
        }());

        lay(that.elem).find('.' + ELEM_RUN_HINT).remove();
        that.elem.appendChild(div);
    };

    //赋值
    Class.prototype.setValue = function (value = '') {
        var that = this
            , options = that.config
            , elem = that.bindElem || options.elem[0]
            , valType = that.isInput(elem) ? 'val' : 'html'

        options.position === 'static' || lay(elem)[valType](value || '');
        elem.textContent = '生成';
        return this;
    };

    //cron校验
    Class.prototype.checkCron = function (fn) {
        var that = this
            , options = that.config
            , lang = that.lang()
            , elem = that.bindElem || options.elem[0]
            , value = that.isInput(elem) ? elem.value : (options.position === 'static' ? '' : elem.innerHTML)

            , checkValid = function (value = "") {

        };

        // cron 值，多个空格替换为一个空格，去掉首尾空格
        value = value || options.value;
        if (typeof value === 'string') {
            value = value.replace(/\s+/g, ' ').replace(/^\s|\s$/g, '');
        }

        if (fn === 'init') return checkValid(value), that;

        value = that.parse();
        if (value) {
            that.setValue(value);
        }
        fn && fn();
        return that;
    };

    //核心入口
    cron.render = function (options) {
        var ins = new Class(options);
        return thisIns.call(ins);
    };

    exports('cron', cron);
});